﻿<Cmdlet(VerbsCommon.Open, "SqlConnection")>
<CmdletBinding(DefaultParameterSetName:="SQL.IWA")>
Public Class OpenSqlConnection
    Inherits PSCmdlet

#Region "ConnectionString"
    <Parameter(ParameterSetName:="SQL.Conn", Mandatory:=True, ValueFromPipelineByPropertyName:=True)>
    <Parameter(ParameterSetName:="Oracle.Conn", Mandatory:=True, ValueFromPipelineByPropertyName:=True)>
    <Parameter(ParameterSetName:="PostGre.Conn", Mandatory:=True, ValueFromPipelineByPropertyName:=True)>
    <Parameter(ParameterSetName:="SQLite.Conn", Mandatory:=True, ValueFromPipelineByPropertyName:=True)>
    Public Property ConnectionString As String
#End Region

#Region "DatabaseType"
    <Parameter(ParameterSetName:="SQL.IWA", ValueFromPipelineByPropertyName:=True)>
    Public Property IWA As SwitchParameter
    <Parameter(ParameterSetName:="Oracle.Conn")>
    <Parameter(ParameterSetName:="Oracle", Mandatory:=True, ValueFromPipelineByPropertyName:=True)>
    Public Property Oracle As SwitchParameter
    <Parameter(ParameterSetName:="PostGre.Conn")>
    <Parameter(ParameterSetName:="PostGre", Mandatory:=True, ValueFromPipelineByPropertyName:=True)>
    Public Property PostGre As SwitchParameter
    <Parameter(ParameterSetName:="SQLite.Conn")>
    <Parameter(ParameterSetName:="SQLite", Mandatory:=True, ValueFromPipelineByPropertyName:=True)>
    Public Property SQLite As SwitchParameter
#End Region

#Region "DataSource"
    <Parameter(ParameterSetName:="SQL", Mandatory:=True, ValueFromPipelineByPropertyName:=True, Position:=1)>
    <Parameter(ParameterSetName:="SQL.IWA", ValueFromPipelineByPropertyName:=True, Position:=1)>
    <Parameter(ParameterSetName:="Oracle", Mandatory:=True, ValueFromPipelineByPropertyName:=True, Position:=1)>
    <Parameter(ParameterSetName:="PostGre", Mandatory:=True, ValueFromPipelineByPropertyName:=True, Position:=1)>
    <Parameter(ParameterSetName:="SQLite", ValueFromPipelineByPropertyName:=True, Position:=1)>
    <[Alias]("Instance", "Server", "SqlInstance")>
    Public Property DataSource As String = "localhost"
#End Region

#Region "InitialCatalog/ServiceName"
    <Parameter(ParameterSetName:="SQL", ValueFrompipelinebypropertyname:=True, Position:=2)>
    <Parameter(ParameterSetName:="SQL.IWA", ValueFrompipelinebypropertyname:=True, Position:=2)>
    <Parameter(ParameterSetName:="PostGre", ValueFrompipelinebypropertyname:=True, Position:=3)>
    <[Alias]("Database")>
    Public Property InitialCatalog As String = "master"

    <Parameter(ParameterSetName:="Oracle", Mandatory:=True, ValueFrompipelinebypropertyname:=True, Position:=3)>
    Public Property ServiceName As String
#End Region

#Region "Port"
    <Parameter(ParameterSetName:="Oracle", ValueFrompipelinebypropertyname:=True, Position:=2)>
    <Parameter(ParameterSetName:="PostGre", ValueFrompipelinebypropertyname:=True, Position:=2)>
    Public Property Port As Integer = 0
#End Region

#Region "User"
    <Parameter(Mandatory:=True, ParameterSetName:="SQL", ValueFrompipelinebypropertyname:=True, Position:=3)>
    <Parameter(Mandatory:=True, ParameterSetName:="Oracle", ValueFrompipelinebypropertyname:=True, Position:=4)>
    <Parameter(Mandatory:=True, ParameterSetName:="PostGre", ValueFrompipelinebypropertyname:=True, Position:=4)>
    Public Property User As String
#End Region

#Region "Password"
    <Parameter(Mandatory:=True, ParameterSetName:="SQL", ValueFrompipelinebypropertyname:=True, Position:=4)>
    <Parameter(Mandatory:=True, ParameterSetName:="Oracle", ValueFrompipelinebypropertyname:=True, Position:=5)>
    <Parameter(Mandatory:=True, ParameterSetName:="PostGre", ValueFrompipelinebypropertyname:=True, Position:=5)>
    <Parameter(ParameterSetName:="SQLite", ValueFromPipelineByPropertyName:=True, Position:=2)>
    Public Property Password As String
#End Region

    <Parameter>
    <[Alias]("TimeOut")>
    Public Property CommandTimeOut As Integer = 30
    <Parameter>
    Public Property ConnectionName As String = "Default"

    Protected Overrides Sub EndProcessing()
        MyBase.EndProcessing()
        If DBInfo.Connections.ContainsKey(ConnectionName) Then
            If ConnectionName = "Default" Then
                ThrowTerminatingError(New ErrorRecord(New DuplicateNameException("Connection is already opened!  Please close it by running Close-SqlConnection"), Nothing, ErrorCategory.InvalidArgument, Nothing))
            Else
                ThrowTerminatingError(New ErrorRecord(New DuplicateNameException(String.Format("Connection '{0}' is already opened!  Please close it by running Close-SqlConnection -ConnectionName {0}", ConnectionName)), Nothing, ErrorCategory.InvalidArgument, Nothing))
            End If

        End If

        Try
            DBInfo.Connections.Add(ConnectionName, GetDBInfo)
        Catch ex As Exception
            DBInfo.Connections.Remove(ConnectionName)
            ThrowTerminatingError(New ErrorRecord(ex, Nothing, ErrorCategory.OpenError, Nothing))
        End Try
    End Sub

    Private Function GetDBInfo() As iDBInfo
        Select Case Me.ParameterSetName
            Case "SQL.IWA"
                Return New dbiSqlClient(Me.ConnectionName, Me.DataSource, Me.InitialCatalog, Me.CommandTimeOut)
            Case "SQL"
                Return New dbiSqlClient(Me.ConnectionName, Me.DataSource, Me.InitialCatalog, Me.CommandTimeOut, Me.User, Me.Password)
            Case "SQL.Conn"
                Return New dbiSqlClient(Me.ConnectionName, Me.ConnectionString, Me.CommandTimeOut)
            Case "Oracle"
                If Me.Port = 0 Then Me.Port = 1521
                Return New dbiOracle(Me.ConnectionName, Me.DataSource, Me.Port, Me.ServiceName, Me.User, Me.Password, Me.CommandTimeOut)
            Case "Oracle.Conn"
                Return New dbiOracle(Me.ConnectionName, Me.ConnectionString, Me.CommandTimeOut)
            Case "PostGre"
                If Me.Port = 0 Then Me.Port = 5432
                If Me.InitialCatalog = "master" Then Me.InitialCatalog = Me.User
                Return New dbiNpgSql(Me.ConnectionName, Me.DataSource, Me.Port, Me.InitialCatalog, Me.User, Me.Password, Me.CommandTimeOut)
            Case "PostGre.Conn"
                Return New dbiNpgSql(Me.ConnectionName, Me.ConnectionString, Me.CommandTimeOut)
            Case "SQLite"
                If Me.DataSource = "localhost" Then Me.DataSource = ":memory:"
                Return New dbiSQLite(Me.ConnectionName, Me.DataSource, Me.Password, Me.CommandTimeOut)
            Case "SQLite.Conn"
                Return New dbiSQLite(Me.ConnectionName, Me.ConnectionString, Me.CommandTimeOut)
            Case Else
                Throw New NotImplementedException(String.Format("ParameterSet '{0}' not implemented.", Me.ParameterSetName))
        End Select
    End Function
End Class
